#include <mpi.h>
#include <stdio.h>
#include "utils.h"
int main(int argc, char** argv) {
    MPI_Init(&argc, &argv);

    int rank, size, msg = 0;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    msg = rank - 100;
    MPI_Comm local_comm, inter_comm;

    // 假设 comm1 和 comm2 已经通过某种方式创建
    // 这里我们简单地将 MPI_COMM_WORLD 分成两部分
    int color = (rank < size / 2);
    MPI_Comm_split(MPI_COMM_WORLD, color, rank, &local_comm);

    //! 创建组间通信子
    if (color == 1) {   // rank = [0,1]
        MPI_Intercomm_create(local_comm, 0, MPI_COMM_WORLD, 2, 0, &inter_comm);
    } else {            // rank = [2,3]
        MPI_Intercomm_create(local_comm, 0, MPI_COMM_WORLD, 0, 0, &inter_comm);
    }
    MPI_Barrier(MPI_COMM_WORLD);
    
    int local_rank, local_size, remote_size;
    MPI_Comm_rank(local_comm, &local_rank);
    MPI_Comm_size(local_comm, &local_size);
    MPI_Comm_remote_size(inter_comm, &remote_size);


    // [INFO]  >> rank: 0, local_rank:0, local_size: 2, remote_size: 2;
    // [INFO]  >> rank: 1, local_rank:1, local_size: 2, remote_size: 2;
    // [INFO]  >> rank: 2, local_rank:0, local_size: 2, remote_size: 2;
    // [INFO]  >> rank: 3, local_rank:1, local_size: 2, remote_size: 2;
    // INFO(" >> rank: %d, local_rank:%d, local_size: %d, remote_size: %d;\n", 
    //                         rank, local_rank, local_size, remote_size);


    //! inter_comm不能获得连接的所有进程的rank
    // int inter_rank, inter_size;
    // MPI_Comm_rank(inter_comm, &inter_rank);
    // MPI_Comm_size(inter_comm, &inter_size);
    // INFO(" >> rank: %d, inter_rank:%d, inter_size: %d;\n", rank, inter_rank, inter_size);

    // // 点对点通信
    if (rank == 0) {
        int target_rank = 1;
        MPI_Send(&msg, 1, MPI_INT, target_rank, 100, inter_comm);
        INFO("rank %d send msg %d to rank %d;\n", rank, msg, local_size +  target_rank);
    } else if (rank == 3) {
        MPI_Recv(&msg, 1, MPI_INT, 0, 100, inter_comm, MPI_STATUS_IGNORE);
        INFO("rank %d recv msg %d from rank %d;\n", rank, msg, 0);
    }

    MPI_Comm_free(&local_comm);
    MPI_Comm_free(&inter_comm);

    MPI_Finalize();
    return 0;
}